package org.dromara.oce.controller.admin;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.dto.TypeDto;
import org.dromara.common.core.enums.FormatsType;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.oce.constant.CommonConstantsJuLang;
import org.dromara.oce.constant.ReferralLinkType;
import org.dromara.oce.domain.OceAdvertiserReferralRelation;
import org.dromara.oce.domain.bo.IaaBackBo;
import org.dromara.oce.domain.bo.OceAdvertiserEverydayCostBo;
import org.dromara.oce.domain.bo.OceSyncCostBo;
import org.dromara.oce.domain.bo.OceSyncOrderBo;
import org.dromara.oce.domain.dto.*;
import org.dromara.oce.domain.vo.OceAdvertiserEverydayCostVo;
import org.dromara.oce.mapper.OceAdvertiserReferralRelationMapper;
import org.dromara.oce.service.OceAdvertiserEverydayCostService;
import org.dromara.oce.service.OceAdvertiserReferralRelationService;
import org.dromara.oce.service.OceEverydayCostHoursService;
import org.dromara.oce.service.OceIaaBackService;
import org.dromara.oce.utils.PlatformParamTransUtil;
import org.dromara.oce.utils.TimeUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 广告主每日消耗记录
 *
 * @author Lion Li
 * @date 2024-12-24
 * @module 管理平台接口
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/oce/advertiserEverydayCost")
public class OceAdvertiserEverydayCostController extends BaseController {

    private final OceAdvertiserReferralRelationMapper referralRelationMapper;
    private final OceAdvertiserEverydayCostService oceEverydayCostService;
    private final OceEverydayCostHoursService oceEverydayCostHoursService;
    private final OceAdvertiserReferralRelationService oceAdvertiserReferralRelationService;
    private final ScheduledExecutorService scheduledExecutorService;
    private final OceIaaBackService oceIaaBackService;

    /**
     * 查询广告主消耗记录列表
     */
    @SaCheckPermission("oce:advertiserEverydayCost:list")
    @GetMapping("/list")
    public TableDataInfo<OceAdvertiserEverydayCostDTO> list(OceAdvertiserEverydayCostBo bo, PageQuery pageQuery) {
        if (Objects.isNull(bo.getIaaFlag())) {
            bo.setIaaFlag(0);
        }
        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("cost");
            pageQuery.setIsAsc("desc");
        }
        Long deptId = LoginHelper.getDeptId();
        if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) {
            bo.setDeptId(deptId);
        }
        Long deptIdCache = PlatformParamTransUtil.getDynamicDept();
        if (deptIdCache > 0L) {
            bo.setDeptId(deptIdCache);
        }
        TableDataInfo<OceAdvertiserEverydayCostDTO> tableDataInfo = new TableDataInfo<>();
        List<OceAdvertiserEverydayCostDTO> dtos = new ArrayList<>();
        List<TypeDto> sum = new ArrayList<>();
        GetOceEverydayCostCensusDataDTO censusDataDto = oceEverydayCostService.sumCost(bo);
        if (Objects.nonNull(censusDataDto)) {
            // 总消耗
            BigDecimal cost = censusDataDto.getCost();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(cost + "");
                typeDto.setDesc("总消耗");
                sum.add(typeDto);
            }
            // 当日总支付笔数
            Integer thatdayPaidTotalNum = censusDataDto.getThatdayPaidTotalNum();
            if (bo.getIaaFlag() != null && bo.getIaaFlag() == 0) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayPaidTotalNum + "");
                typeDto.setDesc("总支付笔数");
                sum.add(typeDto);
            }
            // 当日总收入
            BigDecimal thatdayTotalAmount = censusDataDto.getThatdayTotalAmount();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayTotalAmount + "");
                typeDto.setDesc("当日订单总充值");
                typeDto.setFlag(true);
                sum.add(typeDto);
            }
            // 当日分成金额
            BigDecimal thatdayDividendAmount = censusDataDto.getThatdayDividendAmount();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayDividendAmount + "");
                typeDto.setDesc("当日订单总分成");
                typeDto.setFlag(true);
                sum.add(typeDto);
            }
            // 当日IAA总收入
            BigDecimal iaaTotalAmount = censusDataDto.getIaaTotalAmount();
            if (bo.getIaaFlag() != null && bo.getIaaFlag() == 1) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(iaaTotalAmount + "");
                typeDto.setDesc("当日广告总收入");
                typeDto.setFlag(true);
                sum.add(typeDto);
            }
            // 当日广告分成金额
            BigDecimal iaaDividendAmount = censusDataDto.getIaaDividendAmount();
            if (bo.getIaaFlag() != null && bo.getIaaFlag() == 1) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(iaaDividendAmount + "");
                typeDto.setDesc("当日广告总分成");
                typeDto.setFlag(true);
                sum.add(typeDto);
            }
            //当日总利润
//            BigDecimal thatdayProfitAmount = censusDataDto.getThatdayProfitAmount();
//            if (bo.getIaaFlag() != null) {
//                TypeDto typeDto = new TypeDto();
//                typeDto.setType(thatdayProfitAmount + "");
//                typeDto.setDesc("当日总利润");
//                typeDto.setFlag(true);
//                sum.add(typeDto);
//            }



            // 当日新增总收入
            BigDecimal thatdayRegisterTotalAmount = censusDataDto.getThatdayRegisterTotalAmount();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayRegisterTotalAmount + "");
                typeDto.setDesc("订单充值");
                sum.add(typeDto);
            }
            // 当日新增的分成金额
//            BigDecimal thatdayRegisterDividendAmount = censusDataDto.getThatdayRegisterDividendAmount();
//            if (bo.getIaaFlag() != null) {
//                TypeDto typeDto = new TypeDto();
//                typeDto.setType(thatdayRegisterDividendAmount + "");
//                typeDto.setDesc("订单分成");
//                sum.add(typeDto);
//            }

            // 当日注册用户的IAA总收入
            BigDecimal iaaRegisterTotalAmount = censusDataDto.getIaaRegisterTotalAmount();
            if (bo.getIaaFlag() != null && bo.getIaaFlag() == 1) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(iaaRegisterTotalAmount + "");
                typeDto.setDesc("广告收入");
                sum.add(typeDto);
            }
            // 当日新增的广告分成金额
            BigDecimal iaaRegisterDividendAmount = censusDataDto.getIaaRegisterDividendAmount();
            if (bo.getIaaFlag() != null && bo.getIaaFlag() == 1) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(iaaRegisterDividendAmount + "");
                typeDto.setDesc("账面广告分成");
                sum.add(typeDto);
            }
            // 注册利润金额=当日新增分成金额-当日消耗
            BigDecimal thatdayRegisterProfitAmount = censusDataDto.getThatdayRegisterProfitAmount();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayRegisterProfitAmount + "");
                typeDto.setDesc("账面利润");
                sum.add(typeDto);
            }

            // 新增回本率
            BigDecimal extRegisterRecoveryRate = censusDataDto.getExtRegisterRecoveryRate();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(extRegisterRecoveryRate + "%");
                typeDto.setDesc("回本率");
                sum.add(typeDto);
            }
            // 消耗时速
            BigDecimal costHoursSpeed = censusDataDto.getCostHoursSpeed();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(costHoursSpeed + "");
                typeDto.setDesc("总时速");
                sum.add(typeDto);
            }
            // 当日广告LTV
            BigDecimal attributionMicroGame0dLtv = censusDataDto.getAttributionMicroGame0dLtv();
            if (bo.getIaaFlag() != null && bo.getIaaFlag() == 1) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(attributionMicroGame0dLtv + "");
                typeDto.setDesc("当日广告LTV");
                sum.add(typeDto);
            }
            // 当日广告变现ROI
            BigDecimal attributionMicroGame0dRoi = censusDataDto.getAttributionMicroGame0dRoi();
            if (bo.getIaaFlag() != null && bo.getIaaFlag() == 1) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(attributionMicroGame0dRoi + "");
                typeDto.setDesc("当日广告变现ROI");
                sum.add(typeDto);
            }


            // 当日新增的分成金额
            BigDecimal thatdayDividendAmountSw = censusDataDto.getThatdayDividendAmountSw();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayDividendAmountSw + "");
                typeDto.setDesc("扣点订单分成");
                sum.add(typeDto);
            }
            // 商务当日新增的广告分成金额
            BigDecimal iaaDividendAmountSw = censusDataDto.getIaaDividendAmountSw();
            if (bo.getIaaFlag() != null && bo.getIaaFlag() == 1) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(iaaDividendAmountSw + "");
                typeDto.setDesc("扣点广告分成");
                sum.add(typeDto);
            }
            // 注册利润金额=当日新增分成金额-当日消耗
            BigDecimal thatdayProfitAmountSw = censusDataDto.getThatdayProfitAmountSw();
            if (bo.getIaaFlag() != null) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayProfitAmountSw + "");
                typeDto.setDesc("扣点利润");
                sum.add(typeDto);
            }

        }
        tableDataInfo.setSum(sum);


        TableDataInfo<OceAdvertiserEverydayCostVo> dataInfo = oceEverydayCostService.queryPageList(bo, pageQuery);
        List<OceAdvertiserEverydayCostVo> list = dataInfo.getRows();
        if (CollectionUtils.isNotEmpty(list)) {
            Map<Long,List<TradeOrderIaaBackRecordExcelDTO>> map = new HashMap<>();
            if(bo.getIaaFlag() == 1){
                IaaBackBo boIaa = new IaaBackBo();
                boIaa.setStartDate(bo.getStartDate());
                boIaa.setEndDate(bo.getEndDate());
                List<TradeOrderIaaBackRecordExcelDTO> iaaBacks = oceIaaBackService.queryList(boIaa);
                if (CollectionUtils.isNotEmpty(iaaBacks)) {
                    map = iaaBacks.stream().collect(Collectors.groupingBy(TradeOrderIaaBackRecordExcelDTO::getReferralLinkId));
                }
            }
            for (OceAdvertiserEverydayCostVo vo : list) {
                OceAdvertiserEverydayCostDTO dto = new OceAdvertiserEverydayCostDTO();
                BeanUtil.copyProperties(vo, dto);
                BigDecimal returnRate = vo.getThatdayPaidUseNum() == 0?BigDecimal.ZERO:new BigDecimal(vo.getConvert()).divide(new BigDecimal(vo.getThatdayPaidUseNum()), 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).divide(BigDecimal.ONE, 2, RoundingMode.HALF_UP);
                if(bo.getIaaFlag() == 1) {
                    returnRate = BigDecimal.ZERO;
                }
                dto.setReturnRate(returnRate);
                dto.setReferralLinkTypeDesc(ReferralLinkType.getDescByType(dto.getReferralLinkType()));
                if(bo.getIaaFlag() == 1 && map.containsKey(vo.getReferralLinkId())){
                    Integer advertNums = 0;
                    BigDecimal maxEcpm = BigDecimal.ZERO;
                    BigDecimal ecpmCostSum = BigDecimal.ZERO;
                    BigDecimal avgEcpmSum = BigDecimal.ZERO;
                    List<TradeOrderIaaBackRecordExcelDTO> dtoList = map.get(vo.getReferralLinkId());
                    int count = dtoList.size();
                    for (TradeOrderIaaBackRecordExcelDTO dtoIaa : dtoList) {
                        advertNums += dtoIaa.getAdvertNum();
                        ecpmCostSum = ecpmCostSum.add(dtoIaa.getEcpmCost());
                        avgEcpmSum = avgEcpmSum.add(dtoIaa.getAvgEcpm());
                        if(dtoIaa.getMaxEcpm().compareTo(maxEcpm)>0){
                            maxEcpm = dtoIaa.getMaxEcpm();
                        }
                    }
                    BigDecimal ecpmCost = ecpmCostSum.divide(new BigDecimal(count), 5, RoundingMode.HALF_UP);
                    BigDecimal avgEcpm = avgEcpmSum.divide(new BigDecimal(count), 2, RoundingMode.HALF_UP);
                    BigDecimal advertNum = new BigDecimal(""+advertNums).divide(new BigDecimal(count), 2, RoundingMode.HALF_UP);
                    dto.setAdvertNum(advertNum);
                    dto.setMaxEcpm(maxEcpm);
                    dto.setEcpmCost(ecpmCost);
                    dto.setAvgEcpm(avgEcpm);
                }
                dtos.add(dto);
            }
        }
        tableDataInfo.setCode(dataInfo.getCode());
        tableDataInfo.setMsg(dataInfo.getMsg());
        tableDataInfo.setRows(dtos);
        tableDataInfo.setTotal(dataInfo.getTotal());
        return tableDataInfo;
    }

    /**
     * 广告主消耗记录导出
     */
    @SaCheckPermission("oce:advertiserEverydayCost:export")
    @Log(title = "广告主消耗数据", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(OceAdvertiserEverydayCostBo bo, HttpServletResponse response) {
        if (Objects.isNull(bo.getIaaFlag())) {
            bo.setIaaFlag(0);
        }
        Long deptId = LoginHelper.getDeptId();
        if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) {
            bo.setDeptId(deptId);
        }
        Long deptIdCache = PlatformParamTransUtil.getDynamicDept();
        if (deptIdCache > 0L) {
            bo.setDeptId(deptIdCache);
        }
        List<OceAdvertiserEverydayCostDTO> dtos = new ArrayList<>();
        List<OceAdvertiserEverydayCostVo> list = oceEverydayCostService.queryList(bo);
        if (CollectionUtils.isNotEmpty(list)) {
            for (OceAdvertiserEverydayCostVo vo : list) {
                OceAdvertiserEverydayCostDTO dto = new OceAdvertiserEverydayCostDTO();
                BeanUtil.copyProperties(vo, dto);
                dto.setReferralLinkId(vo.getReferralLinkId()+"");
                dto.setReferralLinkTypeDesc(ReferralLinkType.getDescByType(dto.getReferralLinkType()));
                dtos.add(dto);
            }
        }
        if(CollectionUtils.isNotEmpty(dtos)){
            ExcelUtil.exportExcel(dtos, "广告主消耗数据", OceAdvertiserEverydayCostDTO.class, response);
        }
    }

    /**
     * 查询投手数据列表
     */
    @SaCheckPermission("oce:advertiserEverydayCost:listPitcher")
    @GetMapping("/listPitcher")
    public TableDataInfo<GetOceEverydayCostCensusPitcherDataDTO> listPitcher(OceAdvertiserEverydayCostBo bo, PageQuery pageQuery) {
        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("cost");
            pageQuery.setIsAsc("desc");
        }
        Long deptId = LoginHelper.getDeptId();
        if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) {
            bo.setDeptId(deptId);
        }
        Long deptIdCache = PlatformParamTransUtil.getDynamicDept();
        if (deptIdCache > 0L) {
            bo.setDeptId(deptIdCache);
        }
        TableDataInfo<GetOceEverydayCostCensusPitcherDataDTO> tableDataInfo = oceEverydayCostService.queryPitcherPageList(bo, pageQuery);
        List<TypeDto> sum = new ArrayList<>();
        GetOceEverydayCostCensusDataDTO censusDataDto = oceEverydayCostService.sumCost(bo);
        if (Objects.nonNull(censusDataDto)) {
            // 总消耗
            BigDecimal cost = censusDataDto.getCost();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(cost + "");
                typeDto.setDesc("总消耗");
                sum.add(typeDto);
            }
            // 当日总支付笔数
            Integer thatdayPaidTotalNum = censusDataDto.getThatdayPaidTotalNum();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayPaidTotalNum + "");
                typeDto.setDesc("总支付笔数");
                sum.add(typeDto);
            }
            // 当日总收入
            BigDecimal thatdayTotalAmount = censusDataDto.getThatdayRegisterTotalAmount();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayTotalAmount + "");
                typeDto.setDesc("订单充值");
                sum.add(typeDto);
            }
            // 当日分成金额
            BigDecimal thatdayDividendAmount = censusDataDto.getThatdayRegisterDividendAmount();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayDividendAmount + "");
                typeDto.setDesc("订单分成");
                sum.add(typeDto);
            }
            // 当日利润金额=当日分成金额-当日消耗
            BigDecimal thatdayProfitAmount = censusDataDto.getThatdayRegisterProfitAmount();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayProfitAmount + "");
                typeDto.setDesc("总利润");
                sum.add(typeDto);
            }
            // 回本率
            BigDecimal extRecoveryRate = censusDataDto.getExtRegisterRecoveryRate();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(extRecoveryRate + "%");
                typeDto.setDesc("回本率");
                sum.add(typeDto);
            }
        }
        tableDataInfo.setSum(sum);
        return tableDataInfo;
    }

    /**
     * 导出投手数据列表
     */
    @SaCheckPermission("oce:advertiserEverydayCost:exportPitcher")
    @Log(title = "投手数据", businessType = BusinessType.EXPORT)
    @PostMapping("/exportPitcher")
    public void exportPitcher(OceAdvertiserEverydayCostBo bo, HttpServletResponse response) {
        Long deptId = LoginHelper.getDeptId();
        if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) {
            bo.setDeptId(deptId);
        }
        Long deptIdCache = PlatformParamTransUtil.getDynamicDept();
        if (deptIdCache > 0L) {
            bo.setDeptId(deptIdCache);
        }
        List<GetOceEverydayCostCensusPitcherDataDTO> list = oceEverydayCostService.queryPitcherList(bo);
        ExcelUtil.exportExcel(list, "投手数据记录", GetOceEverydayCostCensusPitcherDataDTO.class, response);
    }

    /**
     * 查询短剧数据列表
     */
    @SaCheckPermission("oce:advertiserEverydayCost:listDrama")
    @GetMapping("/listDrama")
    public TableDataInfo<GetOceEverydayCostCensusDramaDataDTO> listDrama(OceAdvertiserEverydayCostBo bo, PageQuery pageQuery) {
        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("cost");
            pageQuery.setIsAsc("desc");
        }
        Long deptId = LoginHelper.getDeptId();
        if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) {
            bo.setDeptId(deptId);
        }
        Long deptIdCache = PlatformParamTransUtil.getDynamicDept();
        if (deptIdCache > 0L) {
            bo.setDeptId(deptIdCache);
        }
        TableDataInfo<GetOceEverydayCostCensusDramaDataDTO> tableDataInfo = oceEverydayCostService.queryDramaPageList(bo, pageQuery);
        List<TypeDto> sum = new ArrayList<>();
        GetOceEverydayCostCensusDataDTO censusDataDto = oceEverydayCostService.sumCost(bo);
        if (Objects.nonNull(censusDataDto)) {
            // 总消耗
            BigDecimal cost = censusDataDto.getCost();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(cost + "");
                typeDto.setDesc("总消耗");
                sum.add(typeDto);
            }
            // 当日总支付笔数
            Integer thatdayPaidTotalNum = censusDataDto.getThatdayPaidTotalNum();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayPaidTotalNum + "");
                typeDto.setDesc("总支付笔数");
                sum.add(typeDto);
            }
            // 当日总收入
            BigDecimal thatdayTotalAmount = censusDataDto.getThatdayRegisterTotalAmount();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayTotalAmount + "");
                typeDto.setDesc("订单收入");
                sum.add(typeDto);
            }
            // 当日分成金额
            BigDecimal thatdayDividendAmount = censusDataDto.getThatdayRegisterDividendAmount();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayDividendAmount + "");
                typeDto.setDesc("订单分成");
                sum.add(typeDto);
            }
            // 当日利润金额=当日分成金额-当日消耗
            BigDecimal thatdayProfitAmount = censusDataDto.getThatdayRegisterProfitAmount();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(thatdayProfitAmount + "");
                typeDto.setDesc("利润");
                sum.add(typeDto);
            }
            // 回本率
            BigDecimal extRecoveryRate = censusDataDto.getExtRegisterRecoveryRate();
            if (StringUtils.isNotBlank(pageQuery.getIsAsc())) {
                TypeDto typeDto = new TypeDto();
                typeDto.setType(extRecoveryRate + "%");
                typeDto.setDesc("回本率");
                sum.add(typeDto);
            }
        }
        tableDataInfo.setSum(sum);
        return tableDataInfo;
    }

    /**
     * 查询广告主总消耗数据
     */
    @SaCheckPermission("oce:advertiserEverydayCost:sumCost")
    @GetMapping("/sumCost")
    public R<GetOceEverydayCostCensusDataDTO> sumCost(OceAdvertiserEverydayCostBo bo) {
        return R.ok(oceEverydayCostService.sumCost(bo));
    }

    /**
     * 获取广告主消耗记录详细信息
     *
     * @param advertiserCostId 主键
     */
    @SaCheckPermission("oce:advertiserEverydayCost:query")
    @GetMapping("/{advertiserCostId}")
    public R<OceAdvertiserEverydayCostVo> getInfo(@NotNull(message = "主键不能为空")
                                                  @PathVariable Long advertiserCostId) {
        return R.ok(oceEverydayCostService.queryById(advertiserCostId));
    }

    /**
     * 新增广告主消耗记录
     */
    @SaCheckPermission("oce:advertiserEverydayCost:add")
    @Log(title = "广告主消耗记录", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody OceAdvertiserEverydayCostBo bo) {
        return toAjax(oceEverydayCostService.insertByBo(bo));
    }

    /**
     * 修改广告主消耗记录
     */
    @SaCheckPermission("oce:advertiserEverydayCost:edit")
    @Log(title = "广告主消耗记录", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody OceAdvertiserEverydayCostBo bo) {
        return toAjax(oceEverydayCostService.updateByBo(bo));
    }

    /**
     * 删除广告主消耗记录
     *
     * @param advertiserCostIds 主键串
     */
    @SaCheckPermission("oce:advertiserEverydayCost:remove")
    @Log(title = "广告主消耗记录", businessType = BusinessType.DELETE)
    @DeleteMapping("/{advertiserCostIds}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] advertiserCostIds) {
        return toAjax(oceEverydayCostService.deleteWithValidByIds(List.of(advertiserCostIds), true));
    }

    /**
     * 校正消耗
     */
    @SaCheckPermission("oce:advertiserEverydayCost:syncCost")
    @GetMapping("/syncCost")
    public R<Void> syncCost(OceSyncCostBo bo) {
        Long advertiserCostId = bo.getAdvertiserCostId();
        String dateStr = StringUtils.isBlank(bo.getStartDate()) ? DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD, new Date()) : bo.getStartDate();
        // 天的时间戳
        Long dateTimestamp = TimeUtils.getTimestampSecond(dateStr);
        List<OceAdvertiserReferralRelation> batchList = new ArrayList<>();
        if (advertiserCostId > 0L) {
            OceAdvertiserEverydayCostVo advertiserEverydayCost = oceEverydayCostService.queryById(advertiserCostId);
            if (Objects.isNull(advertiserEverydayCost)) {
                return R.fail("消耗记录不存在");
            }
            dateStr = advertiserEverydayCost.getThatdayDate();
            OceAdvertiserReferralRelation relation = oceAdvertiserReferralRelationService.getCacheAdvertiserInfoByReferralLinkId(advertiserEverydayCost.getReferralLinkId());
            if (Objects.nonNull(relation)) {
                batchList.add(relation);
                oceEverydayCostHoursService.syncOceCostData(batchList, dateStr, dateTimestamp);
            }
        } else {
            LambdaQueryWrapper<OceAdvertiserReferralRelation> lqw = Wrappers.lambdaQuery();
            lqw.eq(OceAdvertiserReferralRelation::getPullStatus, CommonConstantsJuLang.PULL_STATUS_ON);
            if (Objects.nonNull(bo.getIaaFlag())) {
                if (bo.getIaaFlag() == 0) {
                    lqw.le(OceAdvertiserReferralRelation::getReferralLinkType, ReferralLinkType.REFERRAL_LINK_TYPE_DIANZHONG.getType());
                } else {
                    lqw.in(OceAdvertiserReferralRelation::getReferralLinkType, ReferralLinkType.REFERRAL_LINK_TYPE_FANQIE_IAA.getType(), ReferralLinkType.REFERRAL_LINK_TYPE_DAISHU_IAA.getType());
                }
            }
            List<OceAdvertiserReferralRelation> referralRelations = referralRelationMapper.selectJobList(lqw);
            if (CollectionUtils.isNotEmpty(referralRelations)) {
                //分批处理
                final int batchSize = 50; //每批次处理的大小
                for (int i = 0; i < referralRelations.size(); i += batchSize) {
                    int endIndex = Math.min(i + batchSize, referralRelations.size());
                    batchList = referralRelations.subList(i, endIndex);
                    String finalDateStr = dateStr;
                    List<OceAdvertiserReferralRelation> finalBatchList = batchList;
                    scheduledExecutorService.schedule(() -> {
                        oceEverydayCostHoursService.syncOceCostData(finalBatchList, finalDateStr, dateTimestamp);
                    }, 2, TimeUnit.SECONDS);
                }
            }
        }
        return R.ok();
    }

    /**
     * 校正充值
     */
    @SaCheckPermission("oce:advertiserEverydayCost:syncOrder")
    @GetMapping("/syncOrder")
    public R<Boolean> syncOrder(OceSyncOrderBo bo) {
        Long advertiserCostId = bo.getAdvertiserCostId();
        Integer iaaFlag = bo.getIaaFlag();
        String dateStr = StringUtils.isBlank(bo.getStartDate()) ? DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD, new Date()) : bo.getStartDate();
        Long referralLinkId = null;
        if (advertiserCostId > 0L) {
            OceAdvertiserEverydayCostVo advertiserEverydayCost = oceEverydayCostService.queryById(advertiserCostId);
            if (Objects.isNull(advertiserEverydayCost)) {
                return R.fail("消耗记录不存在");
            }
            referralLinkId = advertiserEverydayCost.getReferralLinkId();
            dateStr = advertiserEverydayCost.getThatdayDate();
        }
        return R.ok(oceEverydayCostService.syncOrder(referralLinkId, dateStr, iaaFlag == 1));
    }

}
